//
//  WiteBoxStatisticsViewController.m
//  WiteBox
//
//  Created by John Blanco on 6/28/09.
//  Copyright 2009 Effective UI. All rights reserved.
//

#import "WiteBoxStatisticsViewController.h"

#import "TestLocationModel.h"
#import "TestCaseRun.h"
#import "UITestResultsBar.h"
#import "WiteBoxStyles.h"
#import "TestCase.h"
#import "TestRun.h"
#import "WiteBoxTestsViewController.h"

// PRIVATE METHODS
@interface WiteBoxStatisticsViewController (Private)

- (NSString *)randomSuccessMessage;
- (NSString *)randomSomeFailureMessage;
- (NSString *)randomManyFailureMessage;
	
@end

@implementation WiteBoxStatisticsViewController

@synthesize testCaseRunToDisplay;

/*
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
    }
    return self;
}
*/

/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
- (void)loadView {
}
*/

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

	testCaseFailures = [[NSMutableArray alloc] init];
	testCaseSuccesses = [[NSMutableArray alloc] init];

	testResultsBar = [[UITestResultsBar alloc] initWithFrame:CGRectMake(125, 23, self.view.frame.size.width - 125 * 2, 10)];
	
	showTestCasesButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
	showTestCasesButton.frame = CGRectMake(self.view.frame.size.width - 110, self.view.frame.size.height - 39, 100, 31);
	showTestCasesButton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin;
	[showTestCasesButton setTitle:@"Test Cases" forState:UIControlStateNormal];
	[showTestCasesButton addTarget:self action:@selector(testCasesClicked) forControlEvents:UIControlEventTouchUpInside];
	
	passedTestsLabel = [[UILabel alloc] initWithFrame:CGRectMake(57, 6, 68, 43)];
	passedTestsLabel.textColor = [WiteBoxStyles foregroundTextColor];
	passedTestsLabel.backgroundColor = [UIColor clearColor];
	passedTestsLabel.font = [UIFont boldSystemFontOfSize:28.0];
	passedTestsLabel.textAlignment = UITextAlignmentCenter;
	passedTestsLabel.adjustsFontSizeToFitWidth = YES;
	
	failedTestsLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.view.frame.size.width - 125, 6, 68, 43)];
	failedTestsLabel.textColor = [WiteBoxStyles foregroundTextColor];
	failedTestsLabel.backgroundColor = [UIColor clearColor];
	failedTestsLabel.font = [UIFont boldSystemFontOfSize:28.0];
	failedTestsLabel.textAlignment = UITextAlignmentCenter;
	failedTestsLabel.adjustsFontSizeToFitWidth = YES;

	statusLabel1 = [[UILabel alloc] initWithFrame:CGRectMake(20, 51, self.view.frame.size.width - 40, 21)];
	statusLabel1.textColor = [WiteBoxStyles foregroundTextColor];
	statusLabel1.backgroundColor = [UIColor clearColor];
	statusLabel1.font = [UIFont boldSystemFontOfSize:16.0];
	statusLabel1.textAlignment = UITextAlignmentCenter;

	statusLabel2 = [[UILabel alloc] initWithFrame:CGRectMake(20, 73, self.view.frame.size.width - 40, 21)];
	statusLabel2.textColor = [WiteBoxStyles foregroundSubTextColor];
	statusLabel2.backgroundColor = [UIColor clearColor];
	statusLabel2.font = [UIFont boldSystemFontOfSize:14.0];
	statusLabel2.textAlignment = UITextAlignmentCenter;
	
	testRunTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.height - 100)];
	testRunTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
	testRunTableView.backgroundColor = [UIColor clearColor];
	testRunTableView.delegate = self;
	testRunTableView.dataSource = self;
	
	[self.view addSubview:testResultsBar];
	[self.view addSubview:passedTestsLabel];
	[self.view addSubview:failedTestsLabel];
	[self.view addSubview:statusLabel1];
	[self.view addSubview:statusLabel2];
	[self.view addSubview:testRunTableView];
	[self.view addSubview:showTestCasesButton];
	
	self.view.backgroundColor = [WiteBoxStyles backgroundColor];
	
	testResultsBar.value = 0.0;
}

- (void)testCasesClicked {
	if (!witeBoxTestsViewController) {
		witeBoxTestsViewController = [[WiteBoxTestsViewController alloc] init];
		witeBoxTestsViewController.witeBoxStatisticsViewController = self;

		// popup
		popOverController = [[UIPopoverController alloc] initWithContentViewController:witeBoxTestsViewController];
		popOverController.popoverContentSize = CGSizeMake(200, 450);
	}
	
	[popOverController presentPopoverFromRect:showTestCasesButton.frame inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
	
}

// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	return YES;
}

- (void)didReceiveMemoryWarning {
	// Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
	
	// Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
	// Release any retained subviews of the main view.
	// e.g. self.myOutlet = nil;
}


- (void)dealloc {
	[testResultsBar release];
	[passedTestsLabel release];
	[failedTestsLabel release];
	[statusLabel1 release];
	[statusLabel2 release];
	[testCaseSuccesses release];
	[testCaseFailures release];
	[testCaseRunToDisplay release];
	[witeBoxTestsViewController release];
	[super dealloc];
}

#pragma mark -

- (void)updateDisplay {
	NSInteger totalPassingTests = 0;
	NSInteger totalFailingTests = 0;
	NSInteger totalTestCasesExecuted = 0;
	NSInteger totalTestCases = 0;
	NSInteger totalTests = 0;

	TestLocationModel *testLocationModel = [TestLocationModel sharedInstance];

	for (TestCaseRun *iTestCaseRun in testLocationModel.testCaseRuns) {
		if ([iTestCaseRun isCompleted]) {
			totalPassingTests += iTestCaseRun.passingTests;
			totalFailingTests += iTestCaseRun.failingTests;
			totalTestCasesExecuted++;
		}
		
		totalTests += [iTestCaseRun totalTests];
		totalTestCases++;
	}

	if (totalTests > 0) {
		statusLabel1.text = [NSString stringWithFormat:@"Tests %0.0f%% Completed", (double)(totalPassingTests + totalFailingTests) / (double)totalTests * 100.0];
		testResultsBar.value = ((double)totalPassingTests / (double)totalTests);
	} else {
		statusLabel1.text = [NSString stringWithFormat:@"No Tests", totalTests];
		statusLabel2.text = @"Check the Wiki to learn how to create a test.";
		testResultsBar.value = 1.0;
	}

	passedTestsLabel.text = [NSString stringWithFormat:@"%i", totalPassingTests];
	failedTestsLabel.text = [NSString stringWithFormat:@"%i", totalFailingTests];
		
	// when complete
	if (totalTestCases == totalTestCasesExecuted) {
		[testCaseFailures removeAllObjects];
		[testCaseSuccesses removeAllObjects];
		
		// final message (do once)
		if (!messageGenerated) {
			messageGenerated = YES;
			
			if (totalPassingTests == totalTests) {
				statusLabel2.text = [self randomSuccessMessage];
			} else if (totalFailingTests < 4) {
				statusLabel2.text = [self randomSomeFailureMessage];
			} else {
				statusLabel2.text = [self randomManyFailureMessage];
			}
		}
		
		// list of test cases to display
		NSArray *testCaseRuns = nil;
		
		if (testCaseRunToDisplay) {
			testCaseRuns = [NSArray arrayWithObject:testCaseRunToDisplay];
		} else {
			testCaseRuns = testLocationModel.testCaseRuns;
		}
		
		for (TestCaseRun *iTestCaseRun in testCaseRuns) {
			for (TestRun *iTestRun in [iTestCaseRun testRuns]) {
				if (iTestRun.isPassingTest) {
					[testCaseSuccesses addObject:iTestRun];
				} else {
					[testCaseFailures addObject:iTestRun];
				}
			}
		}
		
		[testRunTableView reloadData];
	}		
}

- (NSString *)randomSuccessMessage {
	// all possible messages
	static NSArray *messages = nil;
	
	if (!messages) {
		messages = [[NSArray alloc] initWithObjects:@"You da man!", @"Whoot, there it is!", @"Perfect!", @"Swish!", @"Boom goes the dynamite!", @"Party time!", @"Did you expect anything less?", @"You deserve a raise!", @"Clearly, this app is bug-free.", @"Go on, brag.", @"YES!", @"Smile.", @"Good thing you studied..", nil];
	}

	return [messages objectAtIndex:arc4random()%[messages count]];
}

- (NSString *)randomSomeFailureMessage {
	// all possible messages
	static NSArray *messages = nil;
	
	if (!messages) {
		messages = [[NSArray alloc] initWithObjects:@"Aww, so close!", @"Well, that's not so bad.", @"Code a little better next time, OK?", @"So close.", @"Sorry, man. Just missed it.", @"Aww, shucks!", @"Next time, I want it perfect.", @"Fix it quick before someone sees!", @"Next time I know they'll pass.", @"One more time.", @"Not my bug.", @"Check it in, no one'll notice.", nil]; 
	}
	
	return [messages objectAtIndex:arc4random()%[messages count]];
}

- (NSString *)randomManyFailureMessage {
	// all possible messages
	static NSArray *messages = nil;
	
	if (!messages) {
		messages = [[NSArray alloc] initWithObjects:@"Dude, that's awful.", @"Ever write unit tests before?", @"How much do they pay you?", @"They must pay you by the bug.", @"That's not even close.", @"We could be here all day.", @"Embarrassing.", @"That's the best you could do?", @"Seriously?!", @"This may be a while.", nil];
	}
	
	return [messages objectAtIndex:arc4random()%[messages count]];
}

#pragma mark -

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
	return testCaseSuccesses.count + testCaseFailures.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *CellIdentifier = @"TestCell";
	
	TestRun *testRun = nil;
	
	if (indexPath.row < testCaseFailures.count) {
		testRun = (TestRun *)[testCaseFailures objectAtIndex:indexPath.row]; 
	} else {
		testRun = (TestRun *)[testCaseSuccesses objectAtIndex:indexPath.row - testCaseFailures.count]; 
	}
	
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
		cell.textLabel.font = [UIFont systemFontOfSize:14.0];
		cell.detailTextLabel.font = [UIFont systemFontOfSize:12.0];
		cell.frame = CGRectMake(0, 0, tableView.frame.size.width, 44);
		
		UILabel *actualExpectedLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 13, tableView.frame.size.width - 210, 20)];
		actualExpectedLabel.textColor = [WiteBoxStyles foregroundTextColor];
		actualExpectedLabel.textAlignment = UITextAlignmentRight;
		actualExpectedLabel.backgroundColor = [UIColor clearColor];
		actualExpectedLabel.adjustsFontSizeToFitWidth = YES;
		actualExpectedLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth;
		actualExpectedLabel.minimumFontSize = 6;
		actualExpectedLabel.tag = 100;
		[cell addSubview:actualExpectedLabel];
		
		[actualExpectedLabel release];
    }
	
	cell.backgroundColor = [WiteBoxStyles cellBackgroundColor];
	cell.textLabel.textColor = [WiteBoxStyles cellTextColor];
	cell.textLabel.text = [testRun testMethodName];

	if (!testRun.isPassingTest) {
		if (![[testRun exceptionExpectedValue] isEqualToString:@""]) {
			((UILabel *)[cell viewWithTag:100]).text = [NSString stringWithFormat:@"Expected: %@, Actual: %@", [testRun exceptionExpectedValue], [testRun exceptionActualValue]];
		} else {
			((UILabel *)[cell viewWithTag:100]).text = [NSString stringWithFormat:@"%@", [testRun exceptionActualValue]];
		}
	} else {
		((UILabel *)[cell viewWithTag:100]).text = @"";
	}
	 
	if (!testRun.isTestComplete) {
		cell.textLabel.textColor = [WiteBoxStyles cellTextColor];
		cell.detailTextLabel.text = @"-";
		cell.selectionStyle = UITableViewCellSelectionStyleNone;
	} else {
		if (testRun.isPassingTest) {
			cell.textLabel.textColor = [WiteBoxStyles greenCorrectDarkerContrast];
			cell.detailTextLabel.textColor = [WiteBoxStyles cellTextDetailColor];
			cell.detailTextLabel.text = [NSString stringWithFormat:@"(%0.2fs) Passed", testRun.duration];
			cell.selectionStyle = UITableViewCellSelectionStyleNone;
		} else {
			cell.textLabel.textColor = [WiteBoxStyles redWrongDarkerContrast];
			cell.detailTextLabel.textColor = [WiteBoxStyles cellTextDetailColor];
			cell.detailTextLabel.text = [NSString stringWithFormat:@"(%0.2fs) %@%@", testRun.duration, [testRun exceptionFilename] ? [testRun exceptionFilename] : @"Error", [testRun exceptionLineNumber] >= 0 ? [NSString stringWithFormat:@": Line %i", [testRun exceptionLineNumber]] : @""];
			cell.selectionStyle = UITableViewCellSelectionStyleNone;
		}
	}
	
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
/*	TestRun *testRun = (TestRun *)[[testCaseRun testRuns] objectAtIndex:indexPath.row]; 
	
	if (![testRun isPassingTest]) {
		if (!witeBoxTestDetailViewController) {
			witeBoxTestDetailViewController = [[WiteBoxTestDetailViewController alloc] init];
		}
		
		[self.navigationController pushViewController:witeBoxTestDetailViewController animated:YES];
		[witeBoxTestDetailViewController setTestRun:(TestRun *)[[testCaseRun testRuns] objectAtIndex:indexPath.row]];
	}*/
}

#pragma mark -

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
	showTestCasesButton.hidden = (interfaceOrientation == UIDeviceOrientationLandscapeLeft || interfaceOrientation == UIDeviceOrientationLandscapeRight);		
	
	if (popOverController && [popOverController isPopoverVisible]) {
		[popOverController dismissPopoverAnimated:YES];
	}
}

#pragma mark -

- (void)setTestCaseRunToDisplay:(TestCaseRun *)value {
	[value retain];
	[testCaseRunToDisplay release];
	testCaseRunToDisplay = value;
	
	// redisplay
	[self updateDisplay];
}

@end
